/******************************************************************************
	This file is a part of the Snapshot Bioinformatics Project

	Copyright (C) 2012-2013 Jarom Schow

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/

#include "ProgressDlg.h"

#include <QtCore/QMutex>
#include <QtCore/QTime>
#include <QtCore/QTimer>

#include <QtWidgets/QApplication>
#include <QtWidgets/QCheckBox>
#include <QtWidgets/QLabel>
#include <QtWidgets/QPlainTextEdit>
#include <QtWidgets/QProgressBar>
#include <QtWidgets/QPushButton>
#include <QtWidgets/QStyle>
#include <QtWidgets/QVBoxLayout>

/*****************************
	Definitions
*****************************/

const int	c_textRows = 3;
const int	c_maxVisibleBtns = 3;

/**
	Private Data Class for ProgressDlg
**/
struct ProgressDlgData
{
	ProgressDlgData()
	{ }

	enum {
		UpdateInterval = 1000
	};

	
};

/** Tracks whether we are currently processing application events or not **/
static bool	s_processing = false;

/**
	This function is to keep processEvents() from going into a loop and overflowing the stack.
**/
void processEvents()
{
	if( s_processing )
		return;

	s_processing = true;
	qApp->processEvents();
	s_processing = false;
}

/**
**/
ProgressDlg::ProgressOp::ProgressOp() : m_isActive( false ), m_progressLabel( NULL ), 
	m_progressWgt( NULL ), m_tempSteps( 0 ), m_curSteps( 0 ), m_minSteps( 0 ),
	m_refreshFlags( Clean )
{
}

/**
	@class		ProgressDlg
	@ingroup	Interface
	@nosubgrouping
	@brief		Progress dialog
**/

/**
	Creates a new Progress Dialog as a child of the given widget
**/
ProgressDlg::ProgressDlg( QWidget *parent, const QString &title ) : 
	QDialog( parent ), //Qt::FramelessWindowHint | Qt::WindowTitleHint | Qt::MSWindowsFixedSizeDialogHint ),
	m_event( NULL ), m_refreshFlags( Clean ),
	m_progressLevel( 0 ), m_isEnabled( true ), m_canceled( false ), 
	m_cancelEnabled( false ), m_estimateEnabled( false ), m_elapsedEnabled( false ),
	m_infoWidget( NULL ), m_nextInfoWidget( NULL ), m_busyIndicatorTimer( NULL ),
	m_timerId( 0 ), m_minWidth( 0 ), m_mutex( new QMutex )
{
	setObjectName( "Progress" );
	setModal( true );
	setSizeGripEnabled( false );

	setWindowTitle( title );

	QVBoxLayout *vLayout = new QVBoxLayout( this );

	m_generalLabel = new QLabel( this );
	m_generalLabel->setObjectName( "ProgressLbl" );
	vLayout->addWidget( m_generalLabel );

	m_progressArea = new QWidget( this );
	m_progressArea->setObjectName( "ProgressArea" );
	vLayout->addWidget( m_progressArea );

	m_progressAreaLyt = new QVBoxLayout( m_progressArea );

	for( int i = 0; i < c_maxProgressOps; i++ ){
		ProgressOp	&op = m_progressOps[i];
		
		op.m_progressLabel = new QLabel( m_progressArea );
		op.m_progressLabel->setObjectName( QString( "ProgressLbl_%1" ).arg( i + 1 ) );
		m_progressAreaLyt->addWidget( op.m_progressLabel );
		op.m_progressLabel->hide();

		op.m_progressWgt = new QProgressBar( m_progressArea );
		op.m_progressWgt->setObjectName( QString( "ProgressWgt_%1" ).arg( i + 1 ) );
		m_progressAreaLyt->addWidget( op.m_progressWgt );
		op.m_progressWgt->hide();
	}

	m_progressAreaLyt->addStretch( 100 );

	m_estimateLbl = new QLabel( this );
	m_estimateLbl->setObjectName( "ProgressEstimateLbl" );
	vLayout->addWidget( m_estimateLbl );

	m_elapsedLbl = new QLabel( this );
	m_elapsedLbl->setObjectName("ProgressElapsedLbl");
	vLayout->addWidget( m_elapsedLbl );

	QHBoxLayout *hLayout = new QHBoxLayout();
	vLayout->addLayout( hLayout );

	m_minimizeBtn = new QPushButton( tr( "&Minimize" ), this );
	m_minimizeBtn->setObjectName("ProgressMinimizeBtn");
	hLayout->addWidget( m_minimizeBtn );

	hLayout->addStretch();

	m_cancelBtn = new QPushButton( tr( "&Cancel" ), this );
	m_cancelBtn->setObjectName("ProgressCancelBtn");
	hLayout->addWidget( m_cancelBtn );

	m_busyIndicatorTimer = new QTimer( this );
	m_busyIndicatorTimer->setObjectName( "busyIndicatorTimer" );

	int	minWidth = m_minimizeBtn->width();
	minWidth += m_cancelBtn->width();
	minWidth += style()->pixelMetric( QStyle::PM_LayoutLeftMargin ) * c_maxVisibleBtns;
	minWidth += style()->pixelMetric( QStyle::PM_LayoutRightMargin ) * c_maxVisibleBtns;

	for( int i = 0; i < c_maxProgressOps; i++ ){
		ProgressOp	&op = m_progressOps[i];

		op.m_progressLabel->setMaximumWidth( minWidth );
		op.m_progressWgt->setMinimumWidth( minWidth );
		op.m_progressWgt->setMaximumWidth( minWidth );
	}

	connect( m_busyIndicatorTimer, SIGNAL(timeout()), this, SLOT(step()) );
	connect( m_cancelBtn, SIGNAL(clicked()), this, SLOT(cancelClicked()) );
	connect( m_minimizeBtn, SIGNAL(clicked()), this, SLOT(minimizeClicked()) );

	setLayout( vLayout );

	doLayout();

	setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Maximum );
	layout()->setSizeConstraint( QLayout::SetFixedSize );
}

/**
	Destructor
**/
ProgressDlg::~ProgressDlg()
{
	delete m_mutex;
}

/**
	Reimplemented from QObject to process private refresh events
**/
bool ProgressDlg::event( QEvent *e )
{
	if( e->type() == QEvent::User ){
		refresh();
		return true;
	}

	return QDialog::event( e );
}

/**
	Shows the dialog and starts the progress indicator
**/
int ProgressDlg::start( const QString &info, int totalSteps, bool canCancel, bool elaspeTime )
{
	QMutexLocker	lock( m_mutex );

	if( !m_isEnabled ) //|| !qApp->isRunning() )
		return -1; // ignore if we are outside the main event loop

	int	progID;
	
	if( totalSteps == 0 )
		progID = 0;
	else
		progID = getNextAvailableOp() + 1;

	if( progID > 0 )
	{
		ProgressOp	&op = m_progressOps[progID - 1];

		op.m_isActive = true;

		op.m_info = info;

		op.m_curSteps = 0;
		op.m_tempSteps = 0;
		op.m_totalSteps = totalSteps;
		if( totalSteps > 0 )
		{
			op.m_minSteps = totalSteps / 200;
		}
		else if ( totalSteps < 0 )
		{
			op.m_startTime.start();
		}
				
		op.m_refreshFlags = Dirty;

		m_refreshFlags |= DirtySize;
	}
	else
	{
		m_info = info;
		m_refreshFlags |= DirtyInfo;
	}

	if( m_progressLevel == 0 )
	{
		m_time = 0;
		m_canceled = false;
		m_elapsedEnabled = elaspeTime;

		m_refreshFlags |= DirtyVis;
	}

	if( canCancel )
	{
		m_cancelEnabled = true;
		m_refreshFlags |= DirtyLayout;
	}

	m_progressLevel++;

	needRefresh();

	lock.unlock();

	processEvents();
	processEvents(); // it seems the only way to propagate size changes is a second call to processEvents()

	return progID;
}

/**
**/
void ProgressDlg::pause()
{
	QMutexLocker	lock( m_mutex );
}

/**
**/
void ProgressDlg::resume()
{
	QMutexLocker	lock( m_mutex );
}

/**
**/
void ProgressDlg::cancel()
{
	QMutexLocker	lock( m_mutex );
}

/**
	Closes the dialog and resets the progress indicator
**/
void ProgressDlg::finish( int progID )
{
	QMutexLocker	lock( m_mutex );

	if( progID < 0 || progID > c_maxProgressOps )
		return;

	if( progID > 0 ){
		ProgressOp	&op = m_progressOps[progID - 1];

		if( !op.m_isActive )
			return;

		op.m_isActive = false;
		op.m_progressLabel->hide();
		op.m_progressWgt->hide();

		op.m_refreshFlags |= DirtyVis;
	}
	else
	{
		m_info.clear();
		m_refreshFlags |= DirtyInfo;
	}
	
	if( m_progressLevel < 1 )
		return;

	m_progressLevel--;

	if( m_progressLevel > 0 )
		return;

	m_refreshFlags |= DirtyVis;
	m_refreshFlags |= DirtyLayout;

	m_cancelEnabled = false;

	needRefresh();

	lock.unlock();

	processEvents();
}

/**
**/
void ProgressDlg::enable( bool onOff )
{
	QMutexLocker	lock( m_mutex );

	if( m_isEnabled == onOff )
		return;

	m_isEnabled = onOff;

//	if( !m_isEnabled )
//		hide();
}

/**
	Updates the current status line in the dialog
**/
void ProgressDlg::setInfo( int progID, const QString &info )
{
	QMutexLocker	lock( m_mutex );

	// When progID is -1, we should find the most current progID
	if( progID == -1 ){
		progID = getNextAvailableOp();
	}

	if( progID < 0 || progID > c_maxProgressOps )
		return;

	if( progID == 0 ){
		m_info = info;
		m_refreshFlags |= DirtyInfo;
	}
	else {
		ProgressOp	&op = m_progressOps[progID - 1];

		if( !op.m_isActive )
			return;

		op.m_info = info;
		op.m_refreshFlags |= DirtyInfo;
	}

	needRefresh();

	lock.unlock();

	processEvents();
}

/**
	Advances the progress indicator
**/
void ProgressDlg::stepProgress( int progID, int steps )
{
	QMutexLocker	lock( m_mutex );

	progID -= 1;

	if( progID < 0 || progID >= c_maxProgressOps )
		return;

	ProgressOp	&op = m_progressOps[progID];

	if( !op.m_isActive )
		return;

	if( op.m_totalSteps > 0 )
	{
		// cache the steps, so we only call setProgress() a maximum of 200 times
		// per operation - BIG time savings...
		op.m_tempSteps += steps;

		if( op.m_tempSteps > op.m_minSteps )
		{
			op.m_curSteps += op.m_tempSteps;
			if( op.m_curSteps > op.m_totalSteps )
				op.m_curSteps = op.m_totalSteps;
			op.m_tempSteps = 0;
			op.m_refreshFlags |= DirtyValue;

			needRefresh();
		}
	}
	else if ( op.m_totalSteps < 0 )
	{
		int milli = op.m_startTime.elapsed();
		if ( milli % 500 == 0 )
		{
			op.m_curSteps += 2;
			int w = op.m_progressWgt->width();
			if ( op.m_curSteps >= w )
				op.m_curSteps = 0;
			op.m_refreshFlags |= DirtyValue;
			needRefresh();
		}
	}
	
	lock.unlock();

	processEvents();
}

/**
	Sets the progress indicator to a specific location
**/
void ProgressDlg::setProgress( int progID, int steps )
{
	QMutexLocker	lock( m_mutex );

	progID -= 1;

	if( progID < 0 || progID >= c_maxProgressOps )
		return;

	ProgressOp	&op = m_progressOps[progID];

	if( !op.m_isActive || op.m_curSteps == steps )
		return;

	if( op.m_totalSteps > 0 )
	{
		// cache the steps, so we only call setProgress() a maximum of 200 times
		// per operation - BIG time savings...
		op.m_tempSteps = steps - op.m_curSteps;

		if( op.m_tempSteps > op.m_minSteps || op.m_tempSteps < 0 )
		{
			op.m_curSteps += op.m_tempSteps;
			if( op.m_curSteps > op.m_totalSteps )
				op.m_curSteps = op.m_totalSteps;
			op.m_tempSteps = 0;
			op.m_refreshFlags |= DirtyValue;

			needRefresh();
		}
	}
	else if ( op.m_totalSteps < 0 )
	{
		int milli = op.m_startTime.elapsed();
		if ( milli % 500 == 0 )
		{
			op.m_curSteps += 2;
			int w = op.m_progressWgt->width();
			if ( op.m_curSteps >= w )
				op.m_curSteps = 0;
			op.m_refreshFlags |= DirtyValue;
			needRefresh();
		}
	}

	lock.unlock();

	processEvents();
}

/**
	Resets the progress indicator and estimated/elapsed time displays
**/
void ProgressDlg::reset( int progID )
{
	QMutexLocker	lock( m_mutex );

	progID -= 1;

	if( progID < 0 || progID >= c_maxProgressOps )
		return;

	ProgressOp	&op = m_progressOps[progID];

	if( !op.m_isActive )
		return;

	op.m_info.clear();
	op.m_curSteps = 0;
	op.m_tempSteps = 0;

	op.m_refreshFlags |= DirtyValue;
	op.m_refreshFlags |= DirtyInfo;

	needRefresh();

//	m_estimateLbl->setText( tr( "Estimated Time Remaining: " ) );
//	m_elapsedLbl->setText( tr( "Elapsed Time: " ) );

	lock.unlock();

	processEvents();
}

/**
	Sets whether or not the option to cancel the operation is shown to the user
**/
void ProgressDlg::enableCancel( bool onOff )
{
	QMutexLocker	lock( m_mutex );

	if( m_cancelEnabled == onOff )
		return;

	m_cancelEnabled = onOff;
	m_refreshFlags |= DirtyLayout;

	needRefresh();
}

/**
	Sets whether or not the elapsed time is displayed to the user
**/
void ProgressDlg::enableTimeElapsed( bool onOff )
{
	QMutexLocker	lock( m_mutex );

	if( m_elapsedEnabled == onOff )
		return;

	m_elapsedEnabled = onOff;
	m_refreshFlags |= DirtyLayout;

	needRefresh();
}

/**
	Sets whether or not the time estimate is displayed to the user
**/
void ProgressDlg::enableTimeEstimate( bool onOff )
{
	QMutexLocker	lock( m_mutex );

	if( m_estimateEnabled == onOff )
		return;

	m_estimateEnabled = onOff;
	m_refreshFlags |= DirtyLayout;

	needRefresh();
}

/**
**/
void ProgressDlg::setAdditionalInfoWidget( QWidget *additionalInfo )
{
	QMutexLocker	lock( m_mutex );

	if( m_infoWidget == additionalInfo )
		return;

	m_nextInfoWidget = additionalInfo;
	m_refreshFlags |= DirtyWidget;

	needRefresh();
}

/**
**/
QWidget* ProgressDlg::getAdditionalInfoWidget() const
{
	QMutexLocker	lock( m_mutex );

	return m_infoWidget;
}

/**
**/
bool ProgressDlg::cancelEnabled() const
{
	QMutexLocker	lock( m_mutex );

	return m_cancelEnabled;
}

/**
**/
bool ProgressDlg::timeElapsedEnabled() const
{
	QMutexLocker	lock( m_mutex );

	return m_elapsedEnabled;
}

/**
**/
bool ProgressDlg::timeEstimateEnabled() const
{
	QMutexLocker	lock( m_mutex );

	return m_estimateEnabled;
}

/**
**/
bool ProgressDlg::isCanceled() const
{
	QMutexLocker	lock( m_mutex );

	return m_canceled;
}

/**
**/
bool ProgressDlg::isActive() const
{
	QMutexLocker	lock( m_mutex );

	return (m_progressLevel > 0);
}

/**
**/
bool ProgressDlg::isEnabled() const
{
	QMutexLocker	lock( m_mutex );

	return m_isEnabled;
}

/**
	@return The current position of the progress indicator.
**/
int ProgressDlg::progress( int progID ) const
{
	QMutexLocker	lock( m_mutex );

	if( progID < 1 || progID > c_maxProgressOps )
		return 0;

	const ProgressOp	&op = m_progressOps[progID - 1];

	if( !op.m_isActive )
		return 0;

	return op.m_curSteps;
}

/**
	@return The total number of steps for the progress indicator
**/
int ProgressDlg::totalSteps( int progID ) const
{
	QMutexLocker	lock( m_mutex );

	if( progID < 1 || progID > c_maxProgressOps )
		return 0;

	const ProgressOp	&op = m_progressOps[progID - 1];

	if( !op.m_isActive )
		return 0;

	return op.m_totalSteps;
}

/**
	Notifies the progress dialog of timed updates
**/
void ProgressDlg::timerEvent( QTimerEvent *e )
{
	if( isVisible() ){
		if( m_elapsedEnabled ){
			int time = m_processTimer.elapsed();
			if( time - m_time > 1000 ){
				m_time = time;
				m_elapsedLbl->setText( tr( "Elapsed Time: " ) + getTimeStr( m_time, false ) );
			}
		}
	}
}

/**
	Notifies the dialog of key presses and cancels the progress if the escape button is pressed.
**/
void ProgressDlg::keyPressEvent( QKeyEvent *e )
{
	if( e->key() == Qt::Key_Escape ){
		if( m_cancelBtn->isVisible() )
			cancelClicked();
	}
	else
		QDialog::keyPressEvent( e );
}

/**
**/
void ProgressDlg::step()
{
/*	if( progID < 0 || progID >= c_maxProgressOps )
		return;

	ProgressOp	&op = m_progressOps[progID];

	if( !op.m_isActive )
		return;

	if( op.m_progressWgt->maximum() == 0 )
		op.update( 1 );*/
}

/**
	Notifies the dialog when the user clicks the Cancel button.
**/
void ProgressDlg::cancelClicked()
{
	QMutexLocker	lock( m_mutex );

	m_cancelBtn->hide();
	m_canceled = true;
	emit canceled();
}

/**
	Notifies the dialog when the user clicks the Minimize button
**/
void ProgressDlg::minimizeClicked()
{
	QWidget	*p = (QWidget*) parent();

	if( p )
		p->showMinimized();
}

/**
	This method performs all the updates to the UI - it should only be called from the GUI thread,
	and it locks the mutex so that the state can not be changed while the UI is being updated.
**/
void ProgressDlg::refresh()
{
	QMutexLocker	lock( m_mutex );

	int	i;

	for( i = 0; i < c_maxProgressOps; i++ ){
		ProgressOp	&op = m_progressOps[i];

		if( op.m_refreshFlags == Clean )
			continue;

		if( op.m_refreshFlags & DirtyVis )
		{
			if( op.m_isActive ){
				op.m_progressLabel->show();
				op.m_progressWgt->show();
			}
			else {
				op.m_progressLabel->hide();
				op.m_progressWgt->hide();
			}
		}

		if( op.m_refreshFlags & DirtyRange )
		{
			op.m_progressWgt->setMinimum( 0 );
			if( op.m_totalSteps <= 0 )
				op.m_progressWgt->setTextVisible( false );
			else 
				op.m_progressWgt->setTextVisible( true );

			if ( op.m_totalSteps > 0 )
				op.m_progressWgt->setMaximum( op.m_totalSteps );
			else
				op.m_progressWgt->setMaximum( 0 );
		}

		if( op.m_refreshFlags & DirtyValue ){
			op.m_progressWgt->setValue( op.m_curSteps );
		}
		
		if( op.m_refreshFlags & DirtyInfo )
			op.m_progressLabel->setText( op.m_info );

		op.m_refreshFlags = Clean;
	}

	if( m_refreshFlags & DirtyInfo )
		m_generalLabel->setText( m_info );

	if( m_refreshFlags & DirtyVis ){
		if( m_progressLevel > 0 ){
			m_processTimer.start();

			// update timer - post an update at least every one second.
			m_timerId = startTimer( ProgressDlgData::UpdateInterval );

			setWindowModality( Qt::WindowModal );
			show();
			doLayout();

//			MainWindow::restoreWindowGeometryState( this );
		}
		else {
//			MainWindow::saveWindowGeometryState( this );

			// Hack - if the window was pushed to the background, this must be called before hide(),
			// or the dialog may stay visible until it is hidden again.
			lock.unlock();
			qApp->processEvents();
			lock.relock();

			if( m_timerId ) {
				killTimer( m_timerId );
				m_timerId = 0;
			}

			if( m_elapsedEnabled )
				m_elapsedLbl->setText( QString() );

			m_busyIndicatorTimer->stop();
			m_progressArea->setFixedHeight( 0 );
			hide();
		}
	}

	if( m_refreshFlags & DirtySize ){
		int	height = m_progressAreaLyt->sizeHint().height();

		if( height > m_progressArea->height() )
			m_progressArea->setFixedHeight( height );
	}

	if( m_refreshFlags & DirtyLayout ){
		if( !isHidden() )
			doLayout();
	}

	if( m_refreshFlags & DirtyWidget ){
		if( m_infoWidget ){
			delete m_infoWidget;
			m_infoWidget = NULL;
		}

		m_infoWidget = m_nextInfoWidget;
		m_nextInfoWidget = NULL;

		if( m_infoWidget ){
			m_infoWidget->setParent( this );
		}
	}

	m_refreshFlags = Clean;
	m_event = NULL;
}

/**
	Called from thread-safe functions to trigger an update to the status bar. This function
	assumes that the caller has already locked the mutex. This function is only safe if the
	mutex was locked by the caller. This function creates and posts a refresh event unless
	a refresh event is already pending, ensuring that only one refresh event is pending at
	a time.
**/
void ProgressDlg::needRefresh()
{
	if( m_event )
		return;

	m_event = new QEvent( QEvent::User );
	QApplication::postEvent( this, m_event );
}

/**
**/
int ProgressDlg::getNextAvailableOp()
{
	int	i;

	for( i = 0; i < c_maxProgressOps; i++ ){
		if( !m_progressOps[i].m_isActive )
			return i;
	}

	return -1;
}

/**
	Calculates and displays a time estimate when the given number of steps has been reached
**/
void ProgressDlg::setEstimate( int maximum, int current )
{
	int		time;
	float	fVal;

	if( (!m_estimateEnabled && !m_elapsedEnabled) || current < 1 )
		return;

	time = m_processTimer.elapsed();
	if( time - m_time < 1000 )
		return;

	m_time = time;

	fVal = float( maximum - current );
	fVal = (float(time) * fVal) / float( current );
	time = int( fVal );

	m_estimateLbl->setText( tr( "Estimated Time Remaining: " ) + getTimeStr( time, true ) );
	m_elapsedLbl->setText( tr( "Elapsed Time: " ) + getTimeStr( m_time, false ) );
}

/**
	@return A user readable string representing the time given by @p msec
**/
QString ProgressDlg::getTimeStr( int msec, bool estimate )
{
	int		time = msec / 1000;

	if( time < 60 )
		return QString( tr( " %1 seconds" ) ).arg( time );

	if( time < 120 )
		return QString( tr( " 1 minute %1 seconds" ) ).arg( time % 60 );

	if( time < 3600 ){
		if( estimate )
			return QString( tr( " %1 minutes" ) ).arg( time / 60 );
		else
			return QString( tr( " %1 minutes %2 seconds" ) ).arg( time / 60 ).arg( time % 60 );
	}

	if( time < 7200 ){
		if( estimate )
			return QString( tr( " 1 hour %1 minutes" ) ).arg( time / 60 - 60 );
		else
			return QString( tr( " 1 hour %1 minutes %2 seconds" ) ).arg( time / 60 - 60 ).arg( time % 60 );
	}

	if( estimate )
		return QString( tr( " %1 hours" ) ).arg( time / 3600 );

	return QString( tr( " %1 hours %2 minutes %3 seconds" ) ).arg( time / 3600 ).arg( (time % 3600) / 60 ).arg( time % 60 );
}

/**
	Performs the layout of child widgets
**/
void ProgressDlg::doLayout()
{
	// Time Elapsed -- show when not waiting and requested
	if( m_elapsedEnabled )
		m_elapsedLbl->show();
	else
		m_elapsedLbl->hide();

	// Time Estimated -- show when not waiting and requested
	if( m_estimateEnabled )
		m_estimateLbl->show();
	else
		m_estimateLbl->hide();

	// Additional Information -- show when it exists, whether waiting or not
	if( m_infoWidget )
		m_infoWidget->show();

	// Minimize Button -- show when not waiting
	m_minimizeBtn->show();

	// Cancel Button -- show when not waiting and requested
	if( m_cancelEnabled )
		m_cancelBtn->show();
	else
		m_cancelBtn->hide();
}
